# -*- coding: utf-8 -*-

import git
import os
import uuid

show_dirs = ["_MobaGoArt/Assets/Exporter", "_MobaGoArt/Assets/ArtAssets"]

# 当前分支
current_branch = ""
# 锁
git_lock = False
# 锁钥匙
user_key = uuid.uuid4()


class GitModel(object):

    def __init__(self, git_workspace, key):
        if key != user_key:
            raise Exception("非法调用!")

        self.workspace = git_workspace
        self.git_client = git.Git(git_workspace)
        self.commit_info = []
        self.tags = []
        self.branches = []

    def init(self):
        lock_file = os.path.join(self.workspace, ".git/index.lock")
        if os.path.exists(lock_file):
            os.remove(lock_file)
        self.git_client.execute("git clean -dxf")
        self.git_client.execute("git reset --hard HEAD")
        self._git_update()
        self.update_tags()
        self.update_branches()

    # 加锁
    @staticmethod
    def lock():
        global git_lock
        if git_lock:
            return False, ""
        else:
            git_lock = True
            global user_key
            user_key = uuid.uuid4()

            return True, user_key

    # 解锁
    @staticmethod
    def unlock(key):
        global user_key
        if key != user_key:
            return False

        global git_lock

        if git_lock:
            git_lock = False
        return True

    @staticmethod
    def get_current_branch():
        global current_branch
        return current_branch

    def update_commits(self, branch, since="2.weeks", before="", limit=100):
        global current_branch
        if branch != current_branch and branch in self.branches:
            cmd = 'git checkout ' + branch
            cmd = cmd.encode("gb2312")
            ret = self.git_client.execute(cmd, with_extended_output=True)
            if ret[0] != 0:
                return None
            self._git_update()
            current_branch = branch
        cmd = 'git log --pretty=format:"%h|%an|%ad|%s" --date=format:"%m/%d %H:%M"'
        if since:
            cmd = cmd + ' --since="' + since + '"'
        if before:
            cmd = cmd + ' --before="' + before + '"'

        if limit != 0:
            cmd = cmd + " -" + str(limit)

        for _dir in show_dirs:
            cmd = cmd + " " + _dir
        ret = self.git_client.execute(cmd, with_extended_output=True)

        if ret[0] != 0:
            print ret[1]
            print ret[2]
            return []
        _log_lines = ret[1].split("\n")
        if not len(_log_lines):
            return []

        self.commit_info = []
        # print _log_lines
        for line in _log_lines:
            if line.strip() == "":
                continue
            seg = line.split("|")
            if len(seg) < 4:
                continue
            self.commit_info.append({"CommitId": seg[0],
                                     "Author": seg[1],
                                     "Date": seg[2],
                                     "message": "|".join(seg[3:])})
        return self.commit_info

    def update_tags(self):
        ret = self.git_client.execute("git tag", with_extended_output=True)
        if ret[0] != 0:
            return None
        self.tags = []
        for line in ret[1].split("\n"):
            self.tags.append(line.strip())
        return self.tags

    def update_branches(self):
        global current_branch
        branch_lines = self.git_execute("git branch -a")
        if branch_lines != "error":
            branch_lines = branch_lines.split("\n")
        else:
            branch_lines = []
        self.branches = []

        for line in branch_lines:
            if line.strip().startswith("remotes/origin/"):
                line = line.split("remotes/origin/")[1]
                self.branches.append(line.strip())
            elif line.startswith("* "):
                current_branch = line[2:]
                # self.branches.append(line.strip())
        self.branches.sort()
        return self.branches

    def _git_update(self):
        self.git_execute("git pull")

    def get_diff(self, commit_id1, commit_id2):
        if commit_id1 == "":
            commit_id1 = "HEAD~1"
        cmd = "git diff %s %s --stat --name-only" % (commit_id1, commit_id2)
        for _dir in show_dirs:
            cmd = cmd + " " + _dir

        diff_files = self.git_execute(cmd).split("\n")
        if diff_files == "error":
            diff_files = ""
        return diff_files

    def get_author(self, branch, file_name):
        global current_branch
        if branch != current_branch and branch in self.branches:
            cmd = 'git checkout ' + branch
            ret = self.git_execute(cmd)
            if ret == "error":
                return ""
            current_branch = branch
        cmd = 'git log --pretty=format:"%an|%ad|%s" --date=format:"%Y/%m/%d %H:%M:%S" -1 -- ' + file_name
        return self.git_execute(cmd)

    def get_parent(self, section1, section2):
        cmd = "git merge-base %s %s" % (section1, section2)
        return self.git_execute(cmd)

    def get_commit_date(self, commit_id):
        cmd = 'git show ' + commit_id + ' --pretty=format:"%ad" --date=format:"%Y-%m-%d %H:%M:%S" --name-only'
        return self.git_execute(cmd)

    def get_author_log(self, since):
        cmd = 'git log --pretty=format:"### %an|%ad|%s"  --date=format:"%Y/%m/%d %H:%M:%S" --name-only --since="' + since + '"'
        return self.git_execute(cmd)

    def git_execute(self, cmd):
        cmd = cmd.encode("gb2312")
        ret = self.git_client.execute(cmd, with_extended_output=True)
        if ret[0] != 0:
            return "error"
        return ret[1]

        # def git_operate(self, target, branch, tag):
        #     _cwd = os.getcwd()
        #     os.chdir(target)
        #     logger.show_log("Current git workdir: %s" % target)
        #     _git_lock = "%s/.git/index.lock" % os.path.dirname(target)
        #     if os.path.isfile(_git_lock):
        #         os.remove(_git_lock)
        #
        #     _stderr = ""
        #     try:
        #         # git clean
        #         if self.check_flag("git_clean"):
        #             _git_clean_cmd = "\"%s\" clean -dxf" % self.git_exe
        #             _ret = tool.tools.build_cmd_git(_git_clean_cmd)
        #             if not _ret["ret"]:
        #                 _stderr = _ret["stderr"]
        #                 raise Exception("failed to run %s" % _git_clean_cmd)
        #             # _git_rest_cmd = "\"%s\" reset --hard HEAD" % self.git_exe
        #             _git_rest_cmd = "\"%s\" reset --hard" % self.git_exe
        #             _ret = tool.tools.build_cmd_git(_git_rest_cmd)
        #             if not _ret["ret"]:
        #                 _stderr = _ret["stderr"]
        #                 raise Exception("failed to run %s" % _git_rest_cmd)
        #
        #         # git checkout
        #         if ("" != branch and "switch_git_tag" != branch) or ("switch_git_tag" == branch and "" != tag):
        #             branch = "switch_git_tag" != branch and branch or tag
        #             _git_checkout = "\"%s\" checkout %s" % (self.git_exe, branch[:-2])
        #             # _git_checkout = "\"%s\" checkout origin/%s -b %s" % (self.git_exe, branch, branch)
        #             _ret = tool.tools.build_cmd_git(_git_checkout)
        #             if not _ret["ret"]:
        #                 _stderr = _ret["stderr"]
        #                 raise Exception("failed to run %s" % _git_checkout)
        #         else:
        #             branch = tool.tools.get_git_local_branch(os.path.dirname(target))
        #             if "" == branch:
        #                 branch = tool.tools.get_git_local_branch(target)
        #
        #         # git fetch
        #         if self.check_flag("git_fetch"):
        #             if branch.endswith("_T"):
        #                 self.send_response_common("ignore to git fetch based on git tag branch")
        #             else:
        #                 _git_fetch_cmd = "\"%s\" fetch origin" % self.git_exe
        #                 _ret = tool.tools.build_cmd_git(_git_fetch_cmd)
        #                 if not _ret["ret"]:
        #                     _stderr = _ret["stderr"]
        #                     raise Exception("failed to run %s" % _git_fetch_cmd)
        #
        #         # git pull
        #         if self.check_flag("git_rebase"):
        #             if branch.endswith("_T"):
        #                 self.send_response_common("ignore to git rebase based on git tag branch")
        #             else:
        #                 if not self.check_flag("git_clean"):
        #                     # git stash clear
        #                     _git_stash_clear_cmd = "\"%s\" stash clear" % self.git_exe
        #                     _ret_stash_clear = tool.tools.build_cmd_git(_git_stash_clear_cmd)
        #                     if not _ret_stash_clear["ret"]:
        #                         _stderr = _ret_stash_clear["stderr"]
        #                         raise Exception("failed to run %s" % _git_stash_clear_cmd)
        #                     # git stash
        #                     _git_stash_cmd = "\"%s\" stash" % self.git_exe
        #                     _ret_stash = tool.tools.build_cmd_git(_git_stash_cmd)
        #                     if not _ret_stash["ret"]:
        #                         _stderr = _ret_stash["stderr"]
        #                         raise Exception("failed to run %s" % _git_stash_cmd)
        #
        #                 # _git_pull_cmd = "\"%s\" pull origin" % self.git_exe
        #                 _git_pull_cmd = "\"%s\" rebase origin/%s" % (self.git_exe, branch[:-2])
        #                 _ret_pull = tool.tools.build_cmd_git(_git_pull_cmd)
        #                 if not _ret_pull["ret"]:
        #                     _stderr = _ret_pull["stderr"]
        #                     raise Exception("failed to run %s" % _git_pull_cmd)
        #
        #                 if not self.check_flag("git_clean"):
        #                     # git stash pop
        #                     _git_stash_pop_cmd = "\"%s\" stash pop" % self.git_exe
        #                     _ret_stash_pop = tool.tools.build_cmd_git(_git_stash_pop_cmd)
        #                     if not _ret_stash_pop["ret"]:
        #                         _stderr = _ret_stash_pop["stderr"]
        #                         raise Exception("failed to run %s" % _git_stash_pop_cmd)
        #
        #     except Exception as ex:
        #         self.send_response_error("%s" % ex)
        #         self.error_datail += _stderr + "\n" + traceback.format_exc() + "\n"
        #         return False
        #     finally:
        #         os.chdir(_cwd)
        #     return True

        # if self.check_flag("git_mobagoart"):
        #     if os.path.isdir("%s/Library" % self.moba_goart_proj):
        #         tool.tools.move("%s/Library" % self.moba_goart_proj, self.moba_goart)
        #     _ret_gitgoart = self.git_operate(self.moba_goart_proj, self.build_args["git_mobagoart_branch"],
        #                                      self.build_args["git_mobagoart_tag"])
        #     if os.path.isdir("%s/Library" % self.moba_goart):
        #         tool.tools.move("%s/Library" % self.moba_goart, self.moba_goart_proj)
        #     if not _ret_gitgoart:
        #         return False


if __name__ == '__main__':
    # workspace = "d:/workspace/ai_workspace/tensorflowLearn"
    workspace = "D:\\workspace\\test_workspace\\mobago_art"

